/*================================================================================
// File Name: sha_256_compressor.v
// Author: atom
// Created Time: 2023年11月16日 星期四 21时15分54秒
//
//       *         *********       ****            *         *     
//      * *            *          *    *          * *       * *    
//     *   *           *         *      *        *   *     *   *   
//    *******          *         *      *       *     *   *     *  
//   *       *         *          *    *       *       * *       * 
//  *         *        *           ****       *         *         *
================================================================================*/
`include "sha_256_param.vh"

module sha_256_compressor(
    input                   clk,
    input                   rst_n,

    input   [63:0] [31:0]   din,
    input                   din_vld,

    output  [255:0]         hash_key,
    output                  hash_key_vld
);


wire    [63:0] [31:0]   k;  

assign k[0] = 32'h428a2f98;
assign k[1] = 32'h71374491;
assign k[2] = 32'hb5c0fbcf;
assign k[3] = 32'he9b5dba5;
assign k[4] = 32'h3956c25b;
assign k[5] = 32'h59f111f1;
assign k[6] = 32'h923f82a4;
assign k[7] = 32'hab1c5ed5;
assign k[8] = 32'hd807aa98;
assign k[9] = 32'h12835b01;
assign k[10] = 32'h243185be;
assign k[11] = 32'h550c7dc3;
assign k[12] = 32'h72be5d74;
assign k[13] = 32'h80deb1fe;
assign k[14] = 32'h9bdc06a7;
assign k[15] = 32'hc19bf174;
assign k[16] = 32'he49b69c1;
assign k[17] = 32'hefbe4786;
assign k[18] = 32'h0fc19dc6;
assign k[19] = 32'h240ca1cc;
assign k[20] = 32'h2de92c6f;
assign k[21] = 32'h4a7484aa;
assign k[22] = 32'h5cb0a9dc;
assign k[23] = 32'h76f988da;
assign k[24] = 32'h983e5152;
assign k[25] = 32'ha831c66d;
assign k[26] = 32'hb00327c8;
assign k[27] = 32'hbf597fc7;
assign k[28] = 32'hc6e00bf3;
assign k[29] = 32'hd5a79147;
assign k[30] = 32'h06ca6351;
assign k[31] = 32'h14292967;
assign k[32] = 32'h27b70a85;
assign k[33] = 32'h2e1b2138;
assign k[34] = 32'h4d2c6dfc;
assign k[35] = 32'h53380d13;
assign k[36] = 32'h650a7354;
assign k[37] = 32'h766a0abb;
assign k[38] = 32'h81c2c92e;
assign k[39] = 32'h92722c85;
assign k[40] = 32'ha2bfe8a1;
assign k[41] = 32'ha81a664b;
assign k[42] = 32'hc24b8b70;
assign k[43] = 32'hc76c51a3;
assign k[44] = 32'hd192e819;
assign k[45] = 32'hd6990624;
assign k[46] = 32'hf40e3585;
assign k[47] = 32'h106aa070;
assign k[48] = 32'h19a4c116;
assign k[49] = 32'h1e376c08;
assign k[50] = 32'h2748774c;
assign k[51] = 32'h34b0bcb5;
assign k[52] = 32'h391c0cb3;
assign k[53] = 32'h4ed8aa4a;
assign k[54] = 32'h5b9cca4f;
assign k[55] = 32'h682e6ff3;
assign k[56] = 32'h748f82ee;
assign k[57] = 32'h78a5636f;
assign k[58] = 32'h84c87814;
assign k[59] = 32'h8cc70208;
assign k[60] = 32'h90befffa;
assign k[61] = 32'ha4506ceb;
assign k[62] = 32'hbef9a3f7;
assign k[63] = 32'hc67178f2;


// 1cycle process 8 round
wire    [PIPELINE_NUM:0] [31:0] a,b,c,d,e,f,g,h;
wire    [31:0]                  a_fin,b_fin,c_fin,d_fin,e_fin,f_fin,g_fin,h_fin; 

reg     [PIPELINE_NUM-1:0]      hash_key_vld_d;

assign a[0] = A_INIT;
assign b[0] = B_INIT;
assign c[0] = C_INIT;
assign d[0] = D_INIT;
assign e[0] = E_INIT;
assign f[0] = F_INIT;
assign g[0] = G_INIT;
assign h[0] = H_INIT;

generate
genvar i;
    for(i=0;i<PIPELINE_NUM;i=i+1)
        sha_256_compressor_group x_com_grp_i(
            .clk(clk),
            .rst_n(rst_n),

            .a(a[i]),
            .b(b[i]),
            .c(c[i]),
            .d(d[i]),
            .e(e[i]),
            .f(f[i]),
            .g(g[i]),
            .h(h[i]),
            
            .k(k[(GROUP_NUM*(i+1))-1-:GROUP_NUM]),
            .w(w[(GROUP_NUM*(i+1))-1-:GROUP_NUM]),
        
            .new_a(a[i+1]),
            .new_b(b[i+1]),
            .new_c(c[i+1]),
            .new_d(d[i+1]),
            .new_e(e[i+1]),
            .new_f(f[i+1]),
            .new_g(g[i+1]),
            .new_h(h[i+1])
        );
endgenerate

assign a_fin[31:0] = A_INIT + a[PIPELINE_NUM-1];
assign b_fin[31:0] = A_INIT + b[PIPELINE_NUM-1];
assign c_fin[31:0] = A_INIT + c[PIPELINE_NUM-1];
assign d_fin[31:0] = A_INIT + d[PIPELINE_NUM-1];
assign e_fin[31:0] = A_INIT + e[PIPELINE_NUM-1];
assign f_fin[31:0] = A_INIT + f[PIPELINE_NUM-1];
assign g_fin[31:0] = A_INIT + g[PIPELINE_NUM-1];
assign h_fin[31:0] = A_INIT + h[PIPELINE_NUM-1];

assign hash_key[255:0] = {a_fin[31:0],b_fin[31:0],c_fin[31:0],d_fin[31:0]
                          e_fin[31:0],f_fin[31:0],g_fin[31:0],h_fin[31:0]};

always @(posedge clk or negedge rst_n)begin
    if(!rst_n)
        hash_key_vld_d[PIPELINE_NUM-1:0] <= {PIPELINE_NUM{1'b0}};
    else
        hash_key_vld_d[PIPELINE_NUM-1:0] <= {hash_key_vld_d[PIPELINE_NUM:1],din_vld};
end 

assign hash_key_vld = hash_key_vld_d[PIPELINE_NUM];

endmodule
